﻿using System.Web.Mvc;
using System.Drawing;
using Beeldbankmvc.Code;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using System;
using Beeldbankmvc.Models;
using System.Web;
using System.Configuration;
using Beeldbankmvc.Helpers;
using System.IO;
using System.Web.UI;

namespace Beeldbankmvc.Controllers
{
    [HandleErrorWithELMAH]
    public class MediaServiceController : Controller
    {
        MediaObjectRepository mediaObjectRepository = new MediaObjectRepository();

        // GET: /Index/
        //
        // Fetch image with parameters [100x100-544] (width)x(height)-filenumber or
        // Fetch image with parameters [100-544] (width)-filenumber or
        // Fetch image with parameters [544] filenumber
        //
        // Which generates an image in the format: 544_[100x100].jpg
        [OutputCache(Duration = (3600 * 24), VaryByParam = "*", Location = OutputCacheLocation.Server)]
        public ActionResult Index(string pictureName)
        {
            if (ConfigurationManager.AppSettings["OpenMediaService"] == "true")
            {
                Image TridionImage = CreateImage(pictureName);

                return new ImageResult { Image = TridionImage, ImageFormat = ImageFormat.Jpeg };
            }
            else
                return null;
        }

        public Image CreateImage(string pictureName)
        {
            string regexNewWidthAndHeightSize = "\\[([0-9]*)x([0-9]*)-([0-9]*)\\]";
            string regexNewWidthSize = "\\[([0-9]*)-([0-9]*)\\]";
            string regexOriginalSize = "\\[([0-9]*)\\]";

            RegexOptions options = ((RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline) | RegexOptions.IgnoreCase);

            Regex regNewWidthAndHeightSize = new Regex(regexNewWidthAndHeightSize, options);
            Match matchNewWidthAndHeightSize = regNewWidthAndHeightSize.Match(pictureName);

            Regex regNewWithSize = new Regex(regexNewWidthSize, options);
            Match matchNewWithSize = regNewWithSize.Match(pictureName);

            Regex regOriginalSize = new Regex(regexOriginalSize, options);
            Match matchOriginalSize = regOriginalSize.Match(pictureName);

            bool serveOriginal = false;

            int intRequestedWidth = 0;
            int intRequestedHeight = 0;
            int mediaObjectFileNumber = 0;

            if (matchNewWidthAndHeightSize.Success)
            {
                intRequestedWidth = Convert.ToInt32(matchNewWidthAndHeightSize.Groups[1].Value);
                intRequestedHeight = Convert.ToInt32(matchNewWidthAndHeightSize.Groups[2].Value);
                mediaObjectFileNumber = Convert.ToInt32(matchNewWidthAndHeightSize.Groups[3].Value);
            }
            else if (matchNewWithSize.Success)
            {
                intRequestedWidth = Convert.ToInt32(matchNewWithSize.Groups[1].Value);
                mediaObjectFileNumber = Convert.ToInt32(matchNewWithSize.Groups[2].Value);
            }
            else if (matchOriginalSize.Success)
            {
                mediaObjectFileNumber = Convert.ToInt32(matchOriginalSize.Groups[1].Value);
                serveOriginal = true;
            }

            // Determine first part of the filename
            int mapNumber = mediaObjectFileNumber / Convert.ToInt32(ConfigurationManager.AppSettings["MaxFotosInDirectory"]);
            // Determine first part of the filename
            string fileName = "";
            string fileNameScaledImage = "";

            fileName = ConfigurationManager.AppSettings["FotoArchive"] + "\\" + mapNumber.ToString();

            // Check if directory exists
            Tools.CheckDir(fileName);
            Image TridionImage = null;

            if (!serveOriginal)
            {
                // Check if file was already converted before
                if (intRequestedHeight != 0)
                    fileNameScaledImage = fileName + "\\" + mediaObjectFileNumber.ToString() + "_[" + intRequestedWidth + "x" + intRequestedHeight + "].jpg";
                else
                    fileNameScaledImage = fileName + "\\" + mediaObjectFileNumber.ToString() + "_[" + intRequestedWidth + "].jpg";

                bool exists = System.IO.File.Exists(fileNameScaledImage);

                if (!exists)
                {
                    bool imageHasOriginal = false;
                    Bitmap objBmpImage = new Bitmap(1, 1);
                    Image originalImage = null;

                    // check which original foto is available
                    if (System.IO.File.Exists(fileName + "\\" + mediaObjectFileNumber.ToString() + ".jpg"))
                    {
                        imageHasOriginal = true;
                        originalImage = Image.FromFile(fileName + "\\" + mediaObjectFileNumber.ToString() + ".jpg");
                    }
                    else if (System.IO.File.Exists(fileName + "\\" + mediaObjectFileNumber.ToString() + "_[600].jpg"))
                    {
                        imageHasOriginal = true;
                        originalImage = Image.FromFile(fileName + "\\" + mediaObjectFileNumber.ToString() + "_[600].jpg");
                    }

                    if (originalImage == null)
                    {
                        throw new HttpException(404, "Original image does not exist");
                    }

                    float width = originalImage.Width;
                    float height = originalImage.Height;
                    float heightWidthRatio = width / height;

                    if (intRequestedHeight != 0)
                    {
                        // make sure the image always fits the set width and heigth
                        int iWidth = originalImage.Width;
                        int iHeight = originalImage.Height;
                        // Calculate the Image size if needed
                        if (iWidth > intRequestedWidth || iHeight > intRequestedHeight)
                        {
                            float fRatio = 0;
                            float fRatioWidth = 0;
                            float fRatioHeight = 0;
                            fRatioWidth = ((float)intRequestedWidth / (float)iWidth);
                            fRatioHeight = ((float)intRequestedHeight / (float)iHeight);
                            if (fRatioHeight < fRatioWidth)
                                fRatio = fRatioHeight;
                            else
                                fRatio = fRatioWidth;

                            iWidth = (int)(iWidth * fRatio);
                            iHeight = (int)(iHeight * fRatio);
                        }

                        // Create the thumbnail and set it’s setting
                        objBmpImage = ImageManipulation.GenerateImageThumbnail(originalImage, iWidth, iHeight);
                    }
                    else
                    {
                        objBmpImage = ImageManipulation.GenerateImageThumbnail(originalImage, intRequestedWidth, Convert.ToInt32(intRequestedWidth / heightWidthRatio));
                    }

                    TridionImage = objBmpImage;
                    if (imageHasOriginal)
                    {
                        //Bitmap myBitmap;
                        ImageCodecInfo myImageCodecInfo;

                        // Get an ImageCodecInfo object that represents the TIFF codec.
                        myImageCodecInfo = ImageManipulation.GetEncoderInfo("image/jpeg");

                        // Create an EncoderParameters object.
                        // An EncoderParameters object has an array of EncoderParameter objects
                        EncoderParameters myEncoderParameters = new EncoderParameters(1);
                        myEncoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, 80L);
                        //myEncoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
                        //myEncoderParameters.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.ScanMethod, (int)EncoderValue.ScanMethodInterlaced);
                        //myEncoderParameters.Param[2] = new EncoderParameter(System.Drawing.Imaging.Encoder.RenderMethod, (int)EncoderValue.RenderProgressive); 

                        // Save the bitmap as a JPEG file with compression quality 80.
                        TridionImage.Save(fileNameScaledImage, myImageCodecInfo, myEncoderParameters);
                    }
                }
                else
                {
                    //
                    // Image does not exist, return a black image with a file name
                    //

                    // load existing file
                    Bitmap objBmpImage = new Bitmap(fileNameScaledImage);

                    TridionImage = objBmpImage;
                }
            }
            else
            {
                //
                // Serve the original file
                //
                if (System.IO.File.Exists(fileName + "\\" + mediaObjectFileNumber.ToString() + ".jpg"))
                {
                    fileNameScaledImage = fileName + "\\" + mediaObjectFileNumber.ToString() + ".jpg";
                }
                else if (System.IO.File.Exists(fileName + "\\" + mediaObjectFileNumber.ToString() + "_[600].jpg"))
                {
                    fileNameScaledImage = fileName + "\\" + mediaObjectFileNumber.ToString() + "_[600].jpg";
                }

                // load existing file
                Bitmap objBmpImage = new Bitmap(fileNameScaledImage);
                TridionImage = objBmpImage;
            }
            return TridionImage;
        }

    }
}
